package com.hsnn.medstgmini.sys.dao.impl;

import java.math.BigInteger;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.hsnn.medstgmini.base.dict.dao.impl.BaseHibernateDAO;
import com.hsnn.medstgmini.dao.impl.HibernateSqlUtilImpl;
import com.hsnn.medstgmini.model.Status;
import com.hsnn.medstgmini.model.Whether;
import com.hsnn.medstgmini.sys.dao.SysRoleDao;
import com.hsnn.medstgmini.sys.model.RoleType;
import com.hsnn.medstgmini.sys.model.SysPrivilege;
import com.hsnn.medstgmini.sys.model.SysRole;
import com.hsnn.medstgmini.sys.model.SysUser;
import com.hsnn.medstgmini.util.Pagination;

/**
 * @category 角色
 * @author 蔡春龙
 * @date 2015年6月12日
 */
@Repository
public class SysRoleDaoImpl extends BaseHibernateDAO implements SysRoleDao {

	@Resource(name = "sessionFactory")
	private SessionFactory sessionFactory;
	
	
	@Autowired
	private HibernateSqlUtilImpl dao;
	/**
	 * @category 查询用户所属角色
	 * @date 2015年6月12日
	 * @param user
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<SysRole> getRoleListByUser(SysUser user) {
		Session session = sessionFactory.getCurrentSession();

		StringBuffer sb = new StringBuffer();
		sb.append("select sr.id ");
		sb.append(", sr.name ");
		sb.append(", sr.pid ");
		sb.append(", sr.main ");
		sb.append(", sr.type ");
		sb.append(", sr.level ");
		sb.append(", sr.sort ");
		sb.append(", sr.bound_id ");
		sb.append(", sr.status ");
		sb.append(", sr.remark ");
		sb.append(", sr.create_user_id ");
		sb.append(", sr.create_datetime ");
		sb.append(", sr.upd_user ");
		sb.append(", sr.upd_datetime ");
		sb.append("from sys_role sr join sys_user_role sur ");
		sb.append("on sr.id = sur.role_id  ");
		sb.append("where 1=1 and sur.user_id=:userId ");
		sb.append("order by pid asc, sort asc ");
		SQLQuery query = session.createSQLQuery(sb.toString());
		query.addEntity(SysRole.class);
		query.setString("userId", user.getId());
		return query.list();
	}

	/**
	 * @category 中心查询角色管理列表
	 * @date 2015年6月14日
	 * @param page
	 * @param role
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<SysRole> getZxRoleList(Pagination page, SysRole role) {
		Session session = sessionFactory.getCurrentSession();

		// 拼接列表查询sql
		StringBuffer sbList = new StringBuffer();
		sbList.append("select sr.id ");
		sbList.append(", sr.name ");
		sbList.append(", sr.pid ");
		sbList.append(", sr2.name fatherName ");
		sbList.append(", sr.main ");
		sbList.append(", sr.type ");
		sbList.append(", sr.sort ");
		sbList.append(", sr.bound_id boundId ");
		sbList.append(", sr.status ");
		sbList.append(", sr.remark ");
		sbList.append(", sr.create_user_id createUserId ");
		sbList.append(", sr.create_datetime createDateTime ");
		sbList.append(", sr.upd_user updUser ");
		sbList.append(", sr.upd_datetime updDateTime ");
		sbList.append("from sys_role sr left join sys_role sr2 ");
		sbList.append("on sr.pid = sr2.id ");
		sbList.append("where 1 = 1 ");
		sbList.append("and sr.main = :main ");
		sbList.append("and sr.pid = :pid ");
		if (role != null && StringUtils.isNotBlank(role.getName())) {
			sbList.append("and sr.name like :name ");
		}
		if (role != null && null != role.getStatus()) {
			sbList.append("and sr.status = :status ");
		}
		sbList.append("order by pid asc, sort asc ");

		// 拼接记录数sql
		StringBuffer sbCount = new StringBuffer();
		sbCount.append("select count(*) from ( ");
		sbCount.append(sbList.toString());
		sbCount.append(") t where 1 = 1");

		// 查询个数
		SQLQuery queryCount = session.createSQLQuery(sbCount.toString());
		// 查询列表
		SQLQuery queryList = session.createSQLQuery(sbList.toString());

		// 设置查询条件
		queryCount.setInteger("main", role.getMain());
		queryCount.setString("pid", role.getPid());
		
		queryList.setInteger("main", role.getMain());
		queryList.setString("pid", role.getPid());
		
		if (role != null && StringUtils.isNotBlank(role.getName())) {
			queryCount.setString("name", "%" + role.getName() + "%");
			queryList.setString("name", "%" + role.getName() + "%");
		}
		if (role != null && null != role.getStatus()) {
			queryCount.setInteger("status", role.getStatus());
			queryList.setInteger("status", role.getStatus());
		}
		BigInteger records = ((BigInteger) queryCount.uniqueResult());
		page.setRecords(records.longValue());

		queryList.setFirstResult(page.getFirstResult());
		queryList.setMaxResults(page.getMaxResults());

		return objectToBean(queryList.list());
	}

	/**
	 * @category object结果集转实体类
	 * @date 2015年6月15日
	 * @return
	 */
	private List<SysRole> objectToBean(List<Object[]> objList) {
		List<SysRole> list = new LinkedList<SysRole>();
		if (objList != null) {
			for (Object[] objArray : objList) {
				SysRole role = new SysRole();
				if (objArray[0] != null) {
					role.setId(String.valueOf(objArray[0]));
				}
				if (objArray[1] != null) {
					role.setName(String.valueOf(objArray[1]));
				}
				if (objArray[2] != null) {
					role.setPid(String.valueOf(objArray[2]));
				}
				if (objArray[3] != null) {
					role.setFatherName(String.valueOf(objArray[3]));
				}
				if (objArray[4] != null) {
					role.setMain(Integer.valueOf(String.valueOf(objArray[4])));
				}
				if (objArray[5] != null) {
					role.setType(Integer.valueOf(String.valueOf(objArray[5])));
				}
				if (objArray[6] != null) {
					role.setSort(Integer.valueOf(String.valueOf(objArray[6])));
				}
				if (objArray[7] != null) {
					role.setBoundId(String.valueOf(objArray[7]));
				}
				if (objArray[8] != null) {
					role.setStatus(Integer.valueOf(String.valueOf(objArray[8])));
				}
				if (objArray[9] != null) {
					role.setRemark(String.valueOf(objArray[9]));
				}
				if (objArray[10] != null) {
					role.setCreateUserId(String.valueOf(objArray[10]));
				}
				if (objArray[11] != null) {
					role.setCreateDateTime((Date) objArray[11]);
				}
				if (objArray[12] != null) {
					role.setUpdUser(String.valueOf(objArray[12]));
				}
				if (objArray[13] != null) {
					role.setUpdDateTime((Date) objArray[13]);
				}
				list.add(role);
			}
		}
		return list;
	}

	/**
	 * @category 启用|停用
	 * @param role
	 */
	public void changeStatus(SysRole role) {
		Session session = sessionFactory.getCurrentSession();
		if (role != null) {
			SysRole sr = getRoleById(role.getId());
			if (sr != null) {
				sr.setStatus(role.getStatus());
				sr.setUpdUser(role.getUpdUser());
				sr.setUpdDateTime(new Date());
				session.update(sr);
				session.flush();
			}
		}
	}

	/**
	 * @category 批量(启用|停用)
	 * @param list
	 */
	public void batchChangeStatus(List<SysRole> list) {
		if (list != null && list.size() > 0) {
			for (SysRole role : list) {
				changeStatus(role);
			}
		}
	}

	/**
	 * @category 启用|停用
	 * @param role
	 */
	public void subChangeStatus(SysRole role) {
		Session session = sessionFactory.getCurrentSession();
		if (role != null) {
			SysRole sr = getRoleById(role.getId());
			if (sr != null && sr.getType() == RoleType.custom.getKey()) {
				sr.setStatus(role.getStatus());
				sr.setUpdUser(role.getUpdUser());
				sr.setUpdDateTime(new Date());
				session.update(sr);
				session.flush();
				writeRoleLogSimple(sr.getId());
				if(sr.getLevel() == 2 && sr.getStatus() == 0 ){
					updateByPid(sr.getId(),sr.getLevel());
				}
			}
		}
	}

	
	
	public  void writeRoleLog(List<SysRole> list) {
		if (list != null && list.size() > 0) {
			for (SysRole role : list) {
				subChangeStatus(role);
			}
		}
	}
	
	/**
	 * @category 批量(启用|停用)
	 * @param list
	 */
	public void subBatchChangeStatus(List<SysRole> list) {
		if (list != null && list.size() > 0) {
			for (SysRole role : list) {
				subChangeStatus(role);
			}
		}
	}

	/**
	 * @category 根据id查询角色信息
	 * @date 2015年6月14日
	 * @param id
	 * @return
	 */
	public SysRole getRoleById(String id) {
		Session session = sessionFactory.getCurrentSession();
		Criteria criteria = session.createCriteria(SysRole.class);
		criteria.add(Restrictions.eq("id", id));
		return (SysRole) criteria.uniqueResult();
	}

	/**
	 * @category 中心保存角色信息
	 * @date 2015年6月14日
	 * @param role
	 */
	public void zxSaveRole(SysRole role, List<SysPrivilege> list) {
		Session session = sessionFactory.getCurrentSession();
		if (role != null) {
			// 保存角色信息
			if (StringUtils.isNotBlank(role.getId())) {
				SysRole oldRole = getRoleById(role.getId());
				oldRole.setName(role.getName());
				oldRole.setPid(role.getPid());
				oldRole.setUpdUser(role.getUpdUser());
				oldRole.setStatus(role.getStatus());
				oldRole.setRemark(role.getRemark());
				session.update(oldRole);
			} else {
				role.setId(UUID.randomUUID().toString());
				role.setCreateDateTime(new Date());
				session.save(role);
			}

			// 删除当前角色所有权限
			String hql = "delete from sys_role_privilege where role_id=:roleId ";
			SQLQuery query = session.createSQLQuery(hql);
			query.setString("roleId", role.getId());
			query.executeUpdate();

			// 保存当前角色新权限
			if (list != null) {
				for (SysPrivilege sp : list) {
					hql = "insert into sys_role_privilege values (:roleId, :privilege)";
					query = session.createSQLQuery(hql);
					query.setString("roleId", role.getId());
					query.setString("privilege", sp.getId());
					query.executeUpdate();
				}
			}
			session.flush();
		}
	}
	
	/**
	 * @category 中心保存子角色信息
	 * @author 韩守松
	 * @date   2015年10月16日
	 * @param  @param role
	 */
	public void zxSaveRole(SysRole role) {
		Session session = sessionFactory.getCurrentSession();
		if (role != null) {
			// 保存角色信息
			if (StringUtils.isNotBlank(role.getId())) {//更新
				session.update(role);
			} else {//新增
				role.setId(UUID.randomUUID().toString());
				session.save(role);
			}
			session.flush();
		}
	}

	/**
	 * @category 查询父级角色列表
	 * @date 2015年6月15日
	 * @param exceptRoleId为需要排除的id
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<SysRole> getZxFatherRoleList(String... exceptRoleIds) {
		Session session = sessionFactory.getCurrentSession();
		Criteria criteria = session.createCriteria(SysRole.class);
		criteria.add(Restrictions.eq("status", Status.enabled.getKey()));
		criteria.add(Restrictions.eq("main", Whether.yes.getKey()));
		if (exceptRoleIds != null && exceptRoleIds.length > 0) {
			for (String id : exceptRoleIds) {
				if (StringUtils.isNotBlank(id)) {
					criteria.add(Restrictions.not(Restrictions.eq("id", id)));
				}
			}
		}
		criteria.addOrder(Order.asc("pid"));
		criteria.addOrder(Order.asc("sort"));
		return criteria.list();
	}

	/**
	 * @category 医疗机构、生产企业、配送企业管理员查询公共子角色和自定义子角色管理列表
	 * @date 2015年6月16日
	 * @param page翻页
	 * @param role当前管理员角色
	 * @param userId当前管理员id
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<SysRole> getSubRoleList(Pagination page, SysRole role,
			SysRole editRole, String userId) {
		Session session = sessionFactory.getCurrentSession();
		if (role != null && editRole != null) {
			Criteria criteria = session.createCriteria(SysRole.class);
			criteria.add(Restrictions.eq("pid", role.getId()));
			criteria.add(Restrictions.or(Restrictions.and(
					Restrictions.eq("type", RoleType.common.getKey()),
					Restrictions.eq("status", Status.enabled.getKey())),
					Restrictions.and(
							Restrictions.eq("type", RoleType.custom.getKey()),
							Restrictions.eq("boundId", userId))));
			if (StringUtils.isNotBlank(editRole.getName())) {
				criteria.add(Restrictions.like("name", "%" + editRole.getName()
						+ "%"));
			}
			criteria.addOrder(Order.asc("type"));
			criteria.addOrder(Order.asc("sort"));

			// 查询个数
			criteria.setProjection(Projections.rowCount());
			Long records = (Long) criteria.uniqueResult();
			page.setRecords(records);

			// 查询列表
			criteria.setProjection(null);
			criteria.setFirstResult(page.getFirstResult());
			criteria.setMaxResults(page.getMaxResults());
			return criteria.list();
		}
		return null;
	}

	/**
	 * @category 中心查询角色管理列表
	 * @date 2015年6月14日
	 * @param role
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<SysRole> getZxRoleList() {
		Session session = sessionFactory.getCurrentSession();
		Criteria criteria = session.createCriteria(SysRole.class);
		criteria.add(Restrictions.eq("main", Whether.yes.getKey()));
		criteria.add(Restrictions.eq("status", Status.enabled.getKey()));
		criteria.addOrder(Order.asc("sort"));
		return criteria.list();
	}

	/**
	 * @category 中心、医疗机构、生产企业、配送企业查询子角色列表
	 * @date 2015年6月14日
	 * @param role
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<SysRole> getSubRoleList(SysUser user) {
		Session session = sessionFactory.getCurrentSession();
		if (user != null && user.getRole() != null) {
			SysRole role = user.getRole();
			Criteria criteria = session.createCriteria(SysRole.class);
			criteria.add(Restrictions.eq("pid", role.getId()));
			criteria.add(Restrictions.eq("status", Status.enabled.getKey()));
			criteria.add(Restrictions.or(Restrictions.eq("type",
					RoleType.common.getKey()), Restrictions.and(
					Restrictions.eq("type", RoleType.custom.getKey()),
					Restrictions.eq("boundId", user.getId()))));
			criteria.addOrder(Order.asc("type"));
			criteria.addOrder(Order.asc("sort"));
			List<SysRole> list = criteria.list();
			if (list != null) {
				list.add(0, user.getRole());
			}
			return list;
		}
		return null;
	}

	/**
	 * @category 根据机构id及主账户查询父级id
	 * @author 韩守松
	 * @date   2015年10月16日
	 * @param  @return
	 */
	@SuppressWarnings("unchecked")
	public List<Object[]> getFatherIdList(String roleId,String boundId){
		Session session = sessionFactory.getCurrentSession();
		StringBuffer sql = new StringBuffer();
		sql.append("select id,name from sys_role where level = 2 and pid = :roleId and status = 1 and type=0 ")
		   .append("union select id,name from sys_role where level = 2 and pid = :roleId and bound_id=:boundId and status = 1");
		SQLQuery query = session.createSQLQuery(sql.toString());
		query.setString("roleId", roleId);
		query.setString("boundId", boundId);
		return query.list();
	}
	
	/**
	 * @category 根据主账户id获取主角色id
	 * @author 韩守松
	 * @date   2015年10月19日
	 * @param  @param userRootId
	 * @param  @return
	 */
	public String getUserRoleById(String userRootId){
		Session session = sessionFactory.getCurrentSession();
		StringBuffer hql = new StringBuffer();
		hql.append("select role_id from sys_user_role where user_id = :userRootId ");
		SQLQuery query = session.createSQLQuery(hql.toString());
		query.setString("userRootId", userRootId);
		return query.uniqueResult().toString();
	}
	
	
	@SuppressWarnings("unchecked")
	@Override
	public Pagination getSubRoleList(Pagination page){
		String boundId = page.getConditions().get("boundId");
		String pid = page.getConditions().get("pid");
		String name = page.getConditions().get("name");
		String status = page.getConditions().get("status");
		Map<String,Object> params = new HashMap<String,Object>();
		StringBuffer sql = new StringBuffer()
		   .append("	SELECT  c.name userName,c.status,c.id,c.type as type,c.remark,    ")
		   .append("	c.level,c.pid,  ")
		   .append("	 CASE WHEN (  SELECT a.name FROM  ")
		   .append("    (SELECT name,id FROM sys_role where 1=1 )a  ")
		   .append("	LEFT JOIN ")
		   .append("	(SELECT name,id,pid FROM sys_role where 1=1 )b ON b.pid = a.id    ")
		   .append("     WHERE b.id IS NULL AND a.id = c.id  ")
		   .append("   	) IS NULL THEN 0 ELSE 1 END leaf  ")
		   .append("	FROM sys_role c where c.pid =:pid and type=0");
			if(StringUtils.isNotBlank(name)){
				sql.append(" and c.name like :name ");
			}
			if(StringUtils.isNotBlank(status)){
				sql.append(" and c.status = :status ");
			}
		   sql.append(" union")
		   .append("	SELECT  c.name userName,c.status,c.id,c.type as type,c.remark,    ")
		   .append("	c.level,c.pid,  ")
		   .append("	 CASE WHEN (  SELECT a.name FROM  ")
		   .append("    (SELECT name,id FROM sys_role where 1=1 )a  ")
		   .append("	LEFT JOIN ")
		   .append("	(SELECT name,id,pid FROM sys_role where 1=1 )b ON b.pid = a.id    ")
		   .append("     WHERE b.id IS NULL AND a.id = c.id  ")
		   .append("   	) IS NULL THEN 0 ELSE 1 END leaf  ")
		   .append("	FROM sys_role c  where c.pid = :pid and c.bound_id=:boundId ");
		
		params.put("pid", pid);
		params.put("boundId", boundId);
		if(StringUtils.isNotBlank(name)){
			sql.append(" and c.name like :name ");
			params.put("name", "%"+name+"%");
		}
		if(StringUtils.isNotBlank(status)){
			sql.append(" and c.status = :status ");
			params.put("status", status);
		}
		sql.append(" order by type ");
		
		List<Map<String, Object>> list = (List<Map<String, Object>>) dao.getSqlMapList(sql.toString(), params);
		if (list != null && !list.isEmpty()) {
			for (Map<String, Object> item : list) {
				BigInteger leaf = (BigInteger) item.get("leaf");
				if (leaf != null && leaf.intValue() == 1) {
					item.put("leaf", true);
					item.put("expanded", true);
				} else {
					item.put("leaf", false);
				}
			}
		}
		page.setRows(list);
		return page;
	}
	
	/**
	 * @category 根据父级角色id更新其子角色数据（status）
	 * @author 韩守松
	 * @date   2015年10月21日
	 * @param  @param pid
	 * @param  @param level
	 */
	public void updateByPid(String id,Integer level){
		Session session = sessionFactory.getCurrentSession();
		StringBuffer hql = new StringBuffer();
		hql.append("update sys_role set status = 0 where pid = :id and type = 1 and status = 1 ");
		SQLQuery query = session.createSQLQuery(hql.toString());
		query.setString("id", id);
		query.executeUpdate();
		session.flush();
		
		StringBuffer hqlLog = new StringBuffer();
		hqlLog.append("insert into sys_role_log  ")
		      .append(" select UUID(),sr.* from sys_role sr where sr.pid= :id and type = 1 ");
		Query queryLog = getSession().createSQLQuery(hqlLog.toString());
		queryLog.setString("id", id);
		queryLog.executeUpdate();
		getSession().flush();
	}

 
	@SuppressWarnings("unchecked")
	@Override
	public List<Object> getSubRoleListByType(String roleId,String orgId) {
		StringBuffer sql = new StringBuffer()
		   .append(" select  sr.name,sr.id from sys_role sr  where sr.status=1 and sr.pid=:roleId ")
		   .append(" union ")
		   .append(" select  sr2.name,sr2.id from sys_role sr join  sys_role sr2 on sr.id = sr2.pid ")
		   .append(" where sr.pid=:roleId and sr.bound_id=:orgId and sr.status=1 and sr2.status=1 ");
		Map<String,Object> params = new HashMap<String,Object>();
		params.put("roleId", roleId);
		params.put("orgId", orgId);
		return (List<Object>) dao.getSqlMapList(sql.toString(), params) ;
	}

	@Override
	public void writeRoleLog(String id) {
		StringBuffer hqlLog = new StringBuffer();
		hqlLog.append("insert into sys_role_log  ")
		      .append(" select UUID(),sr.* from sys_role sr where sr.id= :id ");
		Query queryLog = getSession().createSQLQuery(hqlLog.toString());
		queryLog.setString("id", id);
		queryLog.executeUpdate();
		getSession().flush();
	}
	public void writeRoleLogSimple(String id) {
		StringBuffer hqlLog = new StringBuffer();
		hqlLog.append("insert into sys_role_log  ")
		      .append(" select UUID(),sr.* from sys_role sr where sr.id= :id ");
		Query queryLog = getSession().createSQLQuery(hqlLog.toString());
		queryLog.setString("id", id);
		queryLog.executeUpdate();
		getSession().flush();
	}
	public void addRole(SysRole role){
		dao.add(role);
	}
	public void eidtRole(SysRole role){
		dao.update(role);
	}
	public void deleteRole(SysRole role){
		dao.delete(role);
	}
	public List getUserRoleList(String userId){
		String sql = "select a.id,a.name,a.remark,b.role_id from sys_role a left join sys_user_role b on a.id=b.role_id and b.user_id=:userId where a.main=1 order by a.name";
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("userId", userId);
		return dao.getSqlMapList(sql, params);
	}

}
